import axios from 'axios'

import store from '@/store/'
import jsonBig from 'json-bigint'
import { Toast } from 'vant'
import router from '@/router'

const refreshTokenReq = axios.create({
  baseURL: 'http://toutiao.itheima.net/'
})

const request = axios.create({
  baseURL: 'http://toutiao.itheima.net/',
  transformResponse: [
    function(data) {
      try {
        // 如果转换成功则返回转换的数据结果
        return jsonBig.parse(data)
      } catch (err) {
        // 如果转换失败，则包装为统一数据格式并返回
        return {
          data
        }
      }
    }
  ]
})

request.interceptors.request.use(
  function(config) {
    const { user } = store.state

    if (user) {
      config.headers.Authorization = `Bearer ${user.token}`
    }
    return config
  },
  function(error) {
    return Promise.reject(error)
  }
)

// 响应拦截器
// Add a response interceptor
request.interceptors.response.use(
  // 在2xx范围内的任何状态代码都会触发此函数，这里主要用于处理响应数据
  response => {
    return response
  },
  // 任何超出2xx范围的状态码都会触发此函数，这里主要用于处理响应错误
  async function(error) {
    const status = error.response.status
    if (status === 400) {
      // 客户端请求参数错误
      Toast.fail('客户端请求参数异常')
    } else if (status === 401) {
      // token无效
      const { user } = store.state
      if (!user || !user.token) {
        // 跳转登录
        return redirectLogin()
      }
      // 使用refresh_token请求使用新的token
      try {
        const { data } = await refreshTokenReq({
          method: 'PUT',
          url: '/v1_0/authorizations',
          headers: { Authorization: `Bearer ${user.refresh_token}` }
        })

        // 拿到新的token之后更新到容器中
        user.token = data.data.token
        store.commit('setUser', user)

        // 把失败的请求重新发出去
        // error。config是本次请求的相关配置信息对象
        // 这里使用request发请求,它会走自己的拦截器
        // 它的请求拦截器中通过store容器访问 token数据

        return request(error.config)
      } catch (err) {
        // 刷新token都失败了，直接跳转登录页redirectLoginol
        return redirectLogin()
      }
    } else if (status === 403) {
      // 没有权限操作
      Toast.fail('没有权限操作')
    } else if (status >= 500) {
      // 服务端异常
      Toast.fai1('服务端异常，请稍后重试')
    }

    // 将未处理的异常往外抛
    return Promise.reject(error)
  }
)

function redirectLogin() {
  // router.currentRoute 当前路由对象，和你在组件中访问的 this.$route 是同一个东西
  // query 参数的数据格式就是：?key=value&key=value
  // router.push('/login?redirect=' + router.currentRoute.fullPath)
  router.replace({
    name: 'login',
    query: {
      redirect: router.currentRoute.fullPath
    }
  })
}

export default request
